
window.$ = {};
//window.browserPrefix;

(function() {
    var b = document.body || document.documentElement,
    s = b.style,
    p = 'transition',
    v = ['Moz', 'Webkit', 'Khtml', 'O', 'ms'],
    i,
    l = v.length,
    w = window,
    bP,
    dollar = w.$;
    
    if(typeof s[p] === 'string') {return true; }

    // Tests for vendor specific prop,
    p = p.charAt(0).toUpperCase() + p.substr(1);
    for(i=0; i<l; i++) {
      if(typeof s[v[i] + p] === 'string') { 
          bP = v[i].toLowerCase();
          dollar.bt = "-" + bP+"-transform";
          dollar.bae = bP + "AnimationEnd";
          dollar.bte = bP + "TransitionEnd";
          dollar.ban = "-" + bP + "-animation-name";
          dollar.bad = "-" + bP + "-animation-duration";
          dollar.btn = "-" + bP + "-transition";
          dollar.btd = "-" + bP + "-transition-duration";
          w.browserPrefix = bP;
          return true; 
      }
    }
    return false;
})();

    
document.addEventListener("DOMContentLoaded", function() {
    
    var app = new App();
    
}, false);


var utils = {};

/**
 * Returns a string of formatted numbers
 * @author Simon Auner 2011-12-02
 * 
 */
utils.numberFormat = function(number) {
    
    var str = number.toString(),
    rgx = /(\d+)(\d{3})/;
    
    while (rgx.test(str)) {
        str = str.replace(rgx, '$1' + ' ' + '$2');
    }
    return str;
};/*
 * 
 * Cube class
 *    
 **/

function Cube(obj) {
    var me = this,
    el = document.createElement("div"),
    faceContainer = document.createElement("div"),
    faces = [],
    i, sides = 6,
    face,
    random = Math.random,
    round = Math.round,
    size = obj.size,
    halfSize = size/2,
    translateZ = "translateZ(";
    
    
    
    me.el = el;
    el.className = "cube";
    el.style.cssText = "height: " + size + "px; width: " + size + "px;";
    
    
    me.faceContainer = faceContainer;
    faceContainer.style.cssText = "position: relative; margin: 0 auto; height: "+size+"px; width: "+size+"px; " + $.bt + ": -"+browserPrefix+"-transform 0.4s linear; -"+browserPrefix+"-transform-style: preserve-3d;float:left;";    
    el.appendChild(faceContainer);
    
    
    me.onHorseFaceShown = obj.onHorseFaceShown;
    

    
    me.currentFaceId = 0;
    me.yAngle = 0;
    
    // Face one
    
//    faces[0] = document.createElement("div");
//    faces[0].className = "face front";
//    faces[0].style.cssText = "-"+browserPrefix+"-transform: translateZ("+obj.size/2+"px)";
//    faces[0].style.height = (obj.size)+"px";
//    faces[0].style.width = (obj.size)+"px";
//    me.faceContainer.appendChild(me.faces[0]);
    
    
    // Face two
//    me.faces[1] = document.createElement("div");
//    me.faces[1].className = "face";
//    me.faces[1].style.height = (obj.size)+"px";
//    me.faces[1].style.width = (obj.size)+"px";
//    me.faceContainer.appendChild(me.faces[1]);
    
    // Face three
//    me.faces[2] = document.createElement("div");
//    me.faces[2].className = "face";
//    me.faces[2].style.height = (obj.size)+"px";
//    me.faces[2].style.width = (obj.size)+"px";
//    me.faceContainer.appendChild(me.faces[2]);
    
    // Face four
//    me.faces[3] = document.createElement("div");
//    me.faces[3].className = "face";
//    me.faces[3].style.height = (obj.size)+"px";
//    me.faces[3].style.width = (obj.size)+"px";
//    me.faceContainer.appendChild(me.faces[3]);
    
    // Face five
//    me.faces[4] = document.createElement("div");
//    me.faces[4].className = "face";
//    me.faces[4].style.height = (obj.size)+"px";
//    me.faces[4].style.width = (obj.size)+"px";
//    me.faceContainer.appendChild(me.faces[4]);
    
    // Face six
//    me.faces[5] = document.createElement("div");
//    me.faces[5].className = "face";
//    me.faces[5].style.height = (obj.size)+"px";
//    me.faces[5].style.width = (obj.size)+"px";
//    me.faceContainer.appendChild(me.faces[5]);
    
    
    
    
    me.rotateCallback = obj.rotateCallback;
    
    
    
    for(i = 0; i < sides; i++) {
        
        var r = round(100 + random() * 100),
        g = round(100 + random() * 100),
        b = round(100 + random() * 100);
        
        face = document.createElement("div");
        face.className = "face front";
        face.style.cssText = "height: " + (size)+"px; width: " + (size)+"px;background-color : rgb(" + r + "," + g + "," + b + ")";
        faceContainer.appendChild(face);
                
        faces[i] = face;
        
    }
    
    faces[0].style[$.bt] = translateZ + halfSize+"px)";
    faces[0].style.background = "url("  + obj.src + ")";
    faces[0].style.backgroundPosition = -obj.position.x + "px " + -obj.position.y + "px";
    
    faces[1].style[$.bt] = "rotateX(90deg) " + translateZ +halfSize+"px);";
    faces[2].style[$.bt] = "rotateY(90deg) " + translateZ +halfSize+"px)";
    faces[3].style[$.bt] = "rotateY(180deg) " + translateZ +halfSize+"px)";
    faces[4].style[$.bt] = "rotateY(-90deg) " + translateZ +halfSize+"px)";
    faces[5].style[$.bt] = "rotateX(-90deg) " + translateZ +halfSize+"px) rotate(180deg)";
    
    
    me.faces = faces;
    
    // TODO: we should perhaps use clickstart and clickend eventually
    el.addEventListener("mousedown", function() {
        //console.log("Cube click detected!");
        me.rotate();
    }, false);
}

Cube.prototype = {
    getEl : function() {
        return this.el;
    },
    
    quickRotate : function() {
        var me = this,
        r = "rotateX(0deg) rotateY(";
        
        me.yAngle += 90;
        
        me.faceContainer.style[$.bt] = r + me.yAngle+"deg)";
        me.faceContainer.style[$.bt] = r + me.yAngle+"deg)";
        
        me.incFaceId();        
    },
    
    rotate : function() {
        
        var me = this,
        faceContainer = me.faceContainer,
        rotateXY = "rotateX(0deg) rotateY(",
        style = faceContainer.style;
        
        var onRotationEnd = function() {
            faceContainer.removeEventListener($.bte, onRotationEnd, false);
            
            style["-" + browserPrefix+"-transition-duration"] = "0.1s";
            style[$.bt] = rotateXY+me.yAngle+"deg) translate3d(0px,0px,0px) ";
        };
        
        var onTransitionEnd = function() {
            //console.log("Rotate function called!");
            
            faceContainer.removeEventListener($.bte, onTransitionEnd, false);
            
            faceContainer.addEventListener($.bte, onRotationEnd, false);
            
            me.yAngle += 90;
            style[$.btd] = "0.2s";
            style[$.bt] = rotateXY+me.yAngle+"deg)";
            
            me.incFaceId();

            me.rotateCallback.fn.apply(me.rotateCallback.scope, undefined);

        };
        
        faceContainer.addEventListener($.bte, onTransitionEnd, false);
        style[$.btd] = "0.1s";
        style[$.bt] = rotateXY+me.yAngle+"deg) translate3d(0px,4px,4px)";  
        
        
    },
    
    
    
    shuffle : function() {
        //console.log("cube shuffling..");
        var me = this,
        nrRotations = Math.round(Math.random() * 3),
        i;
        
        for (i=0;i<nrRotations;i++) {
            me.quickRotate();
        }
    },
    
    getFaceId : function() {
        // TODO:
        return this.currentFaceId;
    },
    
    /***
     * @author Aram Taieb 2011-12-01
     * @private
     */
    incFaceId : function() {
        var me = this;
        
        me.currentFaceId += 1;
        
        if (me.currentFaceId > 3) {
            me.currentFaceId = 0;
            me.onHorseFaceShown();
        }
    }
};


/**
 * 
 * @author Aram Taieb 2011-11-28
 * @modified Aram Taieb 2011-12-01
 * @param {Object} config 
 * @param {Object} config.levelImages
 */
function Puzzle(config) {
    var me = this;
    
    me.el = document.getElementById("puzzle_container");
    
    me.levelImages = config.levelImages;
    me.setImg(config.size);
    
    // Sizes
    me.puzzleSize = me.el.offsetWidth-40;
    
//    console.log("cubeSize: " + me.cubeSize.toString());
    
    me.callbackWhenSolved  = config.callbackWhenSolved;
    me.callbackScope = config.scope;
    
    me.onHorseFaceShownCallback = config.onHorseFaceShown;
    
    
    // The magical horse cube page index 
    me.horseIdx = 0;
    
    me.createCubeGrid(config.size);
    me.shuffle(); 
}

Puzzle.prototype = {
/**
 * 
 * @author Hans Calmfors 2011-12-01
 */
    createCubeGrid : function(size) {
        var me = this,
        cube,
//        var positionvar = {x:0, y:0};
        cubeSize = parseInt(me.puzzleSize/size-8, 10),
        i, j;
        
        me.size = size;
        me.cubes = [];
        me.setImg(size);
        // row
        for (i=0;i<size;i++)  {
            // One array for each row
            me.cubes.push([]);

            // column
            for (j=0; j<size; j++) {
//                positionvar.x = parseInt(j*cubeSize, 10);
//                positionvar.y = parseInt(i*cubeSize, 10);
//
//                console.log("position.x:" + positionvar.x);
//                console.log("position.y:" + positionvar.y);

                cube = new Cube({
                    size: cubeSize,
                    rotateCallback : {
                        fn: me.onCubeClickedCallback,
                        scope: me
                    },
                    onHorseFaceShown: me.onHorseFaceShownCallback,
                    position: {
                        x : parseInt(j*cubeSize, 10),
                        y : parseInt(i*cubeSize, 10)
                    },
                    src: me.imgSrc
                });

                // TODO: change cube instaniation
                me.cubes[i].push(cube);

                // add to DOM
                me.el.appendChild(cube.getEl());
            }
        }
    },
    
    clearCubeGrid : function() {
        var me = this,
        cubes = me.cubes,
        i, j;
        for (i=0;i<cubes.length;i++)  {
            for (j=0; j<cubes[i].length; j++) {
                me.el.removeChild(cubes[i][j].el);
            }
        }
    },
/**
 * 
 * @author Aram Taieb 2011-11-28
 * @modified Aram Taieb 2011-11-29
 */
    shuffle : function() {
        
//        console.log("shuffling cubes!");
        var me = this,
        i, j,
        s = me.size;

        for (i=0; i<s; i++) {
            for (j=0; j<s; j++) {
                //console.log("shuffling cube (" + i + ", " + j + ")");
                me.cubes[i][j].shuffle();
            }
        }
    },

/**
 * 
 * @author Aram Taieb 2011-11-28
 * @modified Aram Taieb 2011-11-29
 */
    isSolved : function() {
        // If solved
        // Display message
        var me = this,
        i,j,
        s = me.size;

        for (i=0; i<s; i++) {
            for (j=0; j<s; j++) {
                if (me.cubes[i][j].getFaceId() !== me.horseIdx) {
//                    console.log(i + " " + j);
                    return false;
                }
            }
        }
        
//        console.log("SOLVED");
        
        return true;
    
    },

/**
 * 
 * @author Aram Taieb 2011-11-28
 * @modified Aram Taieb 2011-11-29
 */
    onCubeClickedCallback : function() {
        var me = this;

        if (me.isSolved()) {
            
                       
            me.callbackWhenSolved.apply(me.callbackScope, arguments);
        }
    },
    
    setImg : function(puzzleSize) {
        var me = this,
        imgs = me.levelImages,
        img,
        level = puzzleSize-3; // 1,2,3 ...
        
        if (imgs[level] === undefined) {
            img = "img/" + imgs[ Math.round(Math.random() * (imgs.length-1)) ];
        }
        else {
            img = "img/" + imgs[level];
        }
        me.imgSrc = img;
        
        
    }
};




/**
 * 
 * @author Simon Auner 2011-11-28
 * @param {Object} cfg The config object
 * @param {String} cfg.label Button label
 * @param {Function} cfg.callback The function callback when button is pressed
 * @param {Number} cfg.width The width of button in pixels
*/
function Button(cfg) {
    
    var me = this;
    me.button = document.createElement("button");
    var button = me.button;
    
    button.innerText = cfg.label;
    button.className = "clean-gray";
    
    button.style.width = cfg.width + "px";
    
    button.addEventListener("mousedown", function() {
        
    }, false);
    
    button.addEventListener("mouseup", function() {
        cfg.callback();
    }, false);
    
    return button;
    
}

/**
 * 
 * @author Simon Auner 2011-11-28
 * @param {Object} cfg The config object
 * @param {DOMElement} cfg.parentEl The parent element, containing the countdown
 * @param {Function} cfg.callback Callback to execute when the countdown reaches 0
 */
function CountdownTimer(cfg) {
    
    var me = this;
    me.parentEl = cfg.parentEl;
    
    me.el = me.parentEl.appendChild(document.createElement("div"));
    
    me.el.className = "countdownTimer";
    
    
    me.callback = cfg.callback;
    
    
}

CountdownTimer.prototype = {

/**
 * Sets new countdown value
 * @author Simon Auner 2011-11-28
 */
    getNewTime : function() {
        this.timeLeft = this.endTime.getTime() - new Date();
    },

/**
 * The new timer, set to run on an interval
 * @author Simon Auner 2011-11-28
 * 
 */
    timer: function () {
        
        var me = this;
        
        // if we should keep counting, get a new time
        if(me.keepCounting) {
            me.getNewTime();
        }
        
        // if we've reached 0, stop counting and execute callback
        if(me.timeLeft <= 0) {
            
            // stop the interval
            me.keepCounting = false;
            
            // truncate time left to 0
            me.timeLeft = 0;
            
            // clear interval
            clearInterval(me.timerInterval);
            
            me.el.style[$.bt] = "translate3d(0, 50px, 0)";
            me.el.style.opacity = "0";
            
            
            // execute callback
            if(typeof me.callback !== "undefined") {
                me.callback();
            }
        }
        
        // always print output
        me.setOutput();
        
        
        
    },
/**
 * Formats the output in seconds
 * @author Simon Auner 2011-11-28
 * 
 * @param {Number} time Time in milliseconds
 * @returns {Number} Time in seconds (integer)
 */
    formatOutput : function(time) {
        
        // get seconds from milliseconds
        return parseInt(time / 1000, 10); 
        
    },
    
    setText : function(txt) {
        this.el.innerHTML = txt;
    },
    
/**
 * Prints output to the DOM element
 * @author Simon Auner 2011-11-28
 */
    setOutput : function() {
        
        this.el.innerHTML = this.formatOutput(this.timeLeft);
    },
/**
 * Clears the callback of the timer
 * @author Simon Auner 2011-11-28
 */
    clearCallback : function() {
        delete this.callback;
    },

/**
 * Returns the timer start value in seconds
 * @author Simon Auner 2011-11-28
 * @returns {Number} The timer start value
 */
    getTimerStartValue : function() {
        return this.timerStartValue;
    },

/**
 * Start the timer countdown
 * @author Simon Auner 2011-11-28
 * @param {Number} t The number of seconds to countdown from
 */
    start: function (t) {
        var me = this;
        
        me.timerStartValue = t;
        
        me.keepCounting = true;
        
        me.currentTime = new Date();
        me.endTime = new Date();
        me.endTime.setMilliseconds(me.endTime.getMilliseconds() + t + 500);
        
        me.timeLeft = t;
        
        me.setOutput();
        
        me.el.style[$.bt] = "translate3d(0, 0, 0)";
        me.el.style.opacity = "1";
        
        // set up an interval (store it in me to be able to clear later)
        setTimeout(function() {
            me.timerInterval = setInterval(function() {
                me.timer();
            }, 250);
        }, 500);
    },
    
    /**
     * Stops the time
     * @author Aram Taieb 2011-11-30
     * @modified 
     */
    stop : function() {
        clearInterval(this.timerInterval);
    },
    
    shake : function() {
        var el = this.el,
        style = el.style;
        
        var callback = function() {
            
            el.removeEventListener($.bae, callback, false);
            style[$.ban] = "";
        };
        
        el.addEventListener($.bae, callback, false);
        
        style[$.ban] = "shake";
        style[$.bad] = "500ms";
    }
};


function MessageBoxHandler () {
    var me = this,
    
    dimmer = document.createElement("div");
    
    me.msgBoxes = [];
    me.queue = [];
    me.showing = false;
    
    document.body.appendChild(dimmer);
    me.dimmer = dimmer;
    
    dimmer.className = "dimmer";
}

MessageBoxHandler.prototype = {
    
    add : function(msgBox) {
        this.msgBoxes.push(msgBox);
    },
    
    show : function(msgBox, callback) {
        var me = this;
        if(!me.showing) {
            
            me.showing = true;
            
            me.showDimmer();
            
            msgBox.showInDom(callback);
            
        }else{
            me.queue.push(msgBox);
        }
        
    },
    
    hide : function(msgBox) {
        
        this.showing = false;
        this.hideDimmer();
        msgBox.hideInDom();
        
    },
    
    
    showDimmer : function() {
        var style = this.dimmer.style;
        style.display = "block";
        style.opacity = "0.4";
    },
    
    hideDimmer : function() {
        var style = this.dimmer.style;
        style.display = "none";
        style.opacity = "0.0";
    }
    
};
/**
 * 
 * @author Simon Auner 2011-11-28
 * @param {Object} cfg The config object
 * @param {String} [cfg.msg] If provided, will set message text 
 * @param {Object[]} [cfg.buttons] Array of buttons
*/
function MessageBox(cfg) {
    
    if(typeof messageBoxHandler === "undefined") {
        messageBoxHandler = new MessageBoxHandler();
    }
    
    
    
    var me = this,
    msg = document.createElement("div"),
    textContainer,
//    appendChild = msg.appendChild,
    type = cfg.type || "info",
    buttons = cfg.buttons;
    
    
    me.messageBox = msg;
    msg.className = "messageBox alert-message block-message " + type;
    
    
    
    
    if(typeof cfg.msg !== "undefined") {
        textContainer = msg.appendChild(document.createElement("div"));
        textContainer.className = "textContainer";
        textContainer.innerText = cfg.msg;
        me.textContainer = textContainer;
        
    }else if(typeof cfg.el !== "undefined") {
        me.elContainer = msg.appendChild(cfg.el);
    }
    
    
    me.buttonContainer = msg.appendChild(document.createElement("div"));
    me.buttonContainer.className = "buttonContainer";
    

    
    me.animationDuration = 300;
    
    if(typeof buttons !== "undefined") {
        me.createButtons(buttons);
    }
    
    me.quickHide();
    
    messageBoxHandler.add(me);
    
    
    
//    width : 300px;
    
}


MessageBox.prototype = {


/**
 * Adds buttons to the message box
 */
    createButtons : function(arr) {
        var me = this,
         
        
        i, l = arr.length, obj,
        // calculate the button width, take care of spacing in between buttons
        buttonWidth = (me.myWidth - (l - 1) * 5) / l;
        
        for(i = 0; i < l; i++) {
            
            obj = arr[i];
            obj.width = buttonWidth;
            
            me.buttonContainer.appendChild(new Button(arr[i]));
        }
        
    },


/**
 * @author Simon Auner 2011-11-28
 * @param {String} msg New message
 */
    setMessage : function(msg) {
        this.textContainer.innerText = msg;
    },

/**
 * Shows the message box
 * @author Simon Auner 2011-11-28
 */
    show : function(callback) {
        messageBoxHandler.show(this, callback);
    },
    
    showInDom : function(callback) {
        var me = this,
        el = me.messageBox,
        body = document.body,
        style = el.style;
        
        style[$.btn] = $.bt + " " + me.animationDuration + "ms ease-in-out";
        
        
        
        
        body.appendChild(el);
        
        
        
        
        setTimeout(function() {
            

            var clientWidth = body.offsetWidth,
            hCenter = Math.round(clientWidth) / 2,
            leftPos = hCenter - el.offsetWidth / 2,
            
            clientHeight = 550,
            vCenter = Math.round(clientHeight) / 2;
            
            
            style.left = leftPos + "px";
            
            me.topPos = vCenter - el.offsetHeight / 2;
            style.top = me.topPos + "px";
            
            
        }, 10);
        
        if(typeof callback !== "undefined") {
            var fn = function() {
                el.removeEventListener($.bte, fn, false);
                callback();
            }
            el.addEventListener($.bte, fn, false);
        }
        
        setTimeout(function() {
            style[$.bt] = "translateY(0)";
        }, 50);
    },


    hide : function() {
        messageBoxHandler.hide(this);
        
    },

/**
 * Hide the message box
 * @author Simon Auner 2011-11-28
 */
    hideInDom : function(callback) {
        var me = this,
        el = this.messageBox;
        el.style[$.btn] = $.bt + " " + me.animationDuration + "ms ease-in-out";
        
        setTimeout(function() {
            el.style[$.bt] = "translateY(-" + ((me.topPos || 250) + 500) + "px)";
            if(typeof callback !== "undefined") {
                callback();
            }
        }, 10);
        
        
        
    },
    
/**
 * Hide the message box
 * @author Simon Auner 2011-11-28
 */
    quickHide : function() {
        var me = this,
        el = this.messageBox,
        style = el.style;
        style[$.btn] = $.bt + " 0ms";
        
        setTimeout(function() {
            style[$.bt] = "translateY(-" + ((me.topPos || 250) + 500) + "px)";
        }, 10);
        
    },
    
/**
 * Shows the message box
 * @author Simon Auner 2011-11-28
 */
    quickShow: function() {
        var el = this.messageBox,
        style = el.style;
        
        style[$.btn] = $.bt + " 0ms";
        
        setTimeout(function() {
            style[$.bt] = "translateY(0)";
        }, 10);
        
    }
    
    
};


function Statistics() {
    this.createEl();
}




Statistics.prototype = {
    
    createEl : function() {
        
        var container = document.createElement("div"),
        leftDiv = document.createElement("div"),
        rightDiv = document.createElement("div"),
        me = this;
        
        me.el = container;
        container.className = "statistics clearFix";
        
        
        leftDiv.className = "left";
        leftDiv.innerHTML = "Competence<br /> Creativity<br /> Business sense";
        
        
        container.appendChild(leftDiv);
        
        rightDiv.className = "right clearfix";
        me.rightDiv = rightDiv;
        
        container.appendChild(rightDiv);
        me.setPercent(0, 1, 3);
        
    },
    
    setPercent : function(time, level) {
        var me = this,
        i,
        p,
        numberOfBars = 3;
        me.percent = [];
        
        for(i = 0; i < numberOfBars; i++) {
            p = Math.round((Math.random() * 0.1 + 0.3 + ((level - 2)/10)) * 100);
            if(p > 100) {
                p = 100;
            }
            me.percent[i] = p;
                
        }
        me.createBars(numberOfBars);
    },
    
    createBars : function(numberOfBars) {
        
        var me = this,
        i,
        barContainer,
        bar,
        percent;
        
        if(typeof me.bars === "undefined") {
            
            me.bars = [];
            
            for(i = 0; i < numberOfBars; i++) {

                barContainer = document.createElement("div");
                barContainer.className = "barContainer";                

                bar = document.createElement("div");
                bar.className = "bar";
                
                me.bars.push(bar);
                
                percent = me.percent[i];




                bar.style.width = percent + "%";
                bar.innerText = percent + "%";

                barContainer.appendChild(bar);

                me.rightDiv.appendChild(barContainer);

            }
        }else{
            for(i = 0; i < me.bars.length; i++) {


                percent = me.percent[i];
                bar = me.bars[i];

                bar.style.width = percent + "%";
                bar.innerText = percent + "%";

            }
        }
        
    },
    
    setZeroPercent : function() {
        
        var i,
        me = this,
        l = me.percent.length;
        
        for(i = 0; i < l; i++) {
            me.percent[i] = 0;
        }
        me.createBars(l);
        
    },
    
    
    getEl : function() {
        return this.el;
    }
    
};
var global = {};

/**
 * 
 * @author Simon Auner 2011-11-28
 */
function App() {
    var me = this;
    me.init();
    me.puzzlesize = me.puzzlesizeInitValue = 3;
    
    
}

App.prototype = {

/**
 * 
 * @author Simon Auner 2011-11-28
 * @modified Aram Taieb 2011-11-29
 */
    init : function() {
        
        
        
        var me = this,
        
        countdownElContainer = document.createElement("div"),
        
        statistics = new Statistics(),
        
        timer = new CountdownTimer({
            parentEl : countdownElContainer,
            callback : function() {
                
                msg.show();
            }
        
        }),
        audio = document.createElement("audio");
        
        audio.src = "horsie1.mp3";
        
        me.timer = timer;
        countdownElContainer.className = "countdownContainer";
        document.body.appendChild(countdownElContainer);
        
        me.highScores = [];
        me.highScore = 0;
        
        var puzzle = new Puzzle({
            // Win presentation
            callbackWhenSolved : function() {          
                timer.stop();
                
                me.calcHighScore();
                
                subHeaderPointsNumber.innerText = utils.numberFormat(me.highScore);
                subHeaderLevel.innerText = me.puzzlesize - 2;
                
                statistics.setZeroPercent();
                
                timer.setText("WINNING!");
                timer.shake();
                
                setTimeout(function() {
                    winMsg.show(function() {

                        statistics.setPercent(0, me.puzzlesize);
                    });
                }, 1000);
                
            },
            scope: this,
            onHorseFaceShown: function() {
                audio.play();
            },
            levelImages : [
               "1.png", // 1
               "2.png",
               "3.png",
               "4.png",
               "5.png"
            ],
            size: 3
        });        
        
        
        
        
        
        setTimeout(function() {
            timer.start(45000);
        }, 500);
        
        
        
        var msg = new MessageBox({
            msg : "Looks like you were a little bit too slow there, buddy!",
            buttons : [
                {
                    label : "Try again",
                    callback : function() {
                        
                        puzzle.shuffle();
                        
                        timer.start(timer.getTimerStartValue());
                        
                        msg.hide();
                    }
                },
                {
                    label : "Help me!",
                    callback : function() {
                        
                        msg.hide();
                        timer.start(timer.getTimerStartValue() + 10000);
                        
                        me.highScore += -10000;
                        
                        //console.log("highScore: " + me.highScore);
                    }
                }
            ]
        });
        
        var winEl = document.createElement("div"),
        subHeader = document.createElement("h2"),
        header = document.createElement("h1"),
        subHeaderText = document.createElement("span"),
        subHeaderLevel = document.createElement("span"),
        subHeaderPoints = document.createElement("h2"),
        subHeaderPointsText = document.createElement("span"),
        subHeaderPointsNumber = document.createElement("span"),
        text = document.createElement("p"),
        t = "OMG! YOU are the inspiration! You completed the puzzle! <br />";
        
        winEl.className = "winElement";
        winEl.style.cssText = "width: 700px;";
        
        header.className = "texHeader";
        header.innerText = "Congratulations!";
        
        subHeader.className = "texHeader subHeader";
        subHeaderText.innerText = "You completed level ";
        subHeader.appendChild(subHeaderText);
        subHeader.appendChild(subHeaderLevel);
        
        subHeaderPoints.className = "texHeader subHeader";
        subHeaderPointsText.innerText = "Your score: ";
        subHeaderPoints.appendChild(subHeaderPointsText);
        subHeaderPoints.appendChild(subHeaderPointsNumber);
        
        
        text.style.cssText = "text-align: center";
        t+= "Your path to solving the puzzle at this level can be broken down to the following statistics. Good job!";
        text.innerHTML = t;
        
        winEl.appendChild(header);
        winEl.appendChild(subHeader);
        winEl.appendChild(subHeaderPoints);
        winEl.appendChild(text);
        
        
        winEl.appendChild(statistics.getEl());
        
        statistics.setPercent(0, 1);
        
        
        var winMsg = new MessageBox({

            el : winEl,
//           msg: "Horse says: One Netlight!",
            buttons: [
                {
                    label : "Play again!",
                    callback : function() {
                        puzzle.shuffle();
                        timer.start(timer.getTimerStartValue());
                        winMsg.hide();
                    }
                },
                {
                    label : "I want MOAR deep end!",
                    callback : function() {
                        me.puzzlesize++;
                        puzzle.clearCubeGrid();
                        puzzle.createCubeGrid(me.puzzlesize);
                        puzzle.shuffle();
                        timer.start(timer.getTimerStartValue());
                        winMsg.hide();
                    }
                }
            ]
        });
    },
    
    calcHighScore : function() {
        var me = this,
        highScore = 0,
        pzlsize = me.puzzlesize,
        score = Math.round((pzlsize * me.timer.timeLeft)/1000),
        i,
        hs = me.highScores,
        hsl,
        pzlinitval = me.puzzlesizeInitValue;
        
        if (hsl < pzlsize-(pzlinitval+1)) {
            highScores.push(score);
        }
        else {
            hs[pzlsize-pzlinitval] = score;
        }       
        hsl = hs.length;
        for (i=0; i<hsl; i++) {
            highScore += hs[i];
            
            //console.log("highScore calc: " + highScore);
        }
        
        me.highScore = highScore;
    }
    
};
